package govenor.overwatch;

import govenor.status.FileStoreStatus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import model.jena.properties.FileStore;
import networkdescriptor.NetworkDescriptor;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;

import constants.NetworkConstants;

public class FileStoreNode{
	private FileStoreStatus fileStoreStatus;
	private HashMap<String,FileStoreStatus> fileSatus;
	private NetworkDescriptor heartbeatDetails ;
	private NetworkDescriptor fileUploadDetails ;
	private NetworkDescriptor fileDownloadDetails ;
	private NetworkDescriptor commandDetails;
	
	public FileStoreNode() {
		fileSatus = new HashMap<String, FileStoreStatus>();
		fileStoreStatus = new FileStoreStatus();
		heartbeatDetails = new NetworkDescriptor();
		heartbeatDetails.setHostname("localhost") ;
		heartbeatDetails.setPortNumber(NetworkConstants.DEFAULT_HB_PORT);
	}
	public FileStoreNode(String hbHostname, int hbPortNumber) {
		fileSatus = new HashMap<String, FileStoreStatus>();
		fileStoreStatus = new FileStoreStatus();
		heartbeatDetails = new NetworkDescriptor();
		heartbeatDetails.setHostname(hbHostname) ;
		heartbeatDetails.setPortNumber(hbPortNumber);
	}
	public void setHeartBeatNetworkDescription(String hostname, int port){
		if(heartbeatDetails == null){
			heartbeatDetails = new NetworkDescriptor(hostname, port);
		}else{
			heartbeatDetails.setHostname(hostname);
			heartbeatDetails.setPortNumber(port);
		}
	}
	public void setfileUploadNetworkDescription(String hostname, int port){
		if(fileUploadDetails == null){
			fileUploadDetails = new NetworkDescriptor(hostname, port);
		}else{
			fileUploadDetails.setHostname(hostname);
			fileUploadDetails.setPortNumber(port);
		}
	}
	public void setfileDownloadNetworkDescription(String hostname, int port){
		if(fileDownloadDetails == null){
			fileDownloadDetails = new NetworkDescriptor(hostname, port);
		}else{
			fileDownloadDetails.setHostname(hostname);
			fileDownloadDetails.setPortNumber(port);
		}
	}
	public void setCommandNetworkDescription(String hostname, int port){
		if(commandDetails == null){
			commandDetails = new NetworkDescriptor(hostname, port);
		}else{
			commandDetails.setHostname(hostname);
			commandDetails.setPortNumber(port);
		}
	}
	public NetworkDescriptor getHeartBeatNetworkDescription(){
		return this.heartbeatDetails;
	}
	public NetworkDescriptor getFileUploadNetworkDescription(){
		return this.fileUploadDetails;
	}
	public NetworkDescriptor getFileDownloadNetworkDescription(){
		return this.fileDownloadDetails ;
	}
	public NetworkDescriptor getCommandNetworkDescription(){
		return this.commandDetails;
	}
	public void updateStatusOfFile(FileStoreStatus updateStatus){
		this.fileStoreStatus = updateStatus;
	}
	public FileStoreStatus getFileStatus(String fileName){
		return this.fileSatus.get(fileName);
	}
	public void updateStatsForFilesInStore(Model model){
		ResIterator resourceIterator = model.listSubjectsWithProperty(FileStore.FILENAME);
		List<Resource> listOfResources = resourceIterator.toList();
		if(listOfResources != null && listOfResources.size() > 0){
			//Check for deleted files
			if(this.fileSatus.size() != listOfResources.size()){
				Set<String> filesInMap = this.fileSatus.keySet();
				Iterator<String> filename = filesInMap.iterator();
				while(filename.hasNext()){
					String name = filename.next();
					boolean found = false;
					for(int i = 0; i < listOfResources.size(); i++){
						if(name.equalsIgnoreCase(listOfResources.get(i).getProperty(FileStore.FILENAME).getString())){
							found = true;
						}
					}
					if(!found){
						this.fileSatus.remove(name);
					}
				}
			}
			for(int i =0; i < listOfResources.size(); i++){
				String filename = listOfResources.get(i).getProperty(FileStore.FILENAME).getString();
				if(this.fileSatus.containsKey(filename)){
					FileStoreStatus stats = this.fileSatus.get(filename);
					stats.setAverageServiceTime(listOfResources.get(i).getProperty(FileStore.AVG_SERVICE_TIME).getDouble());
					stats.setNumberOfDownloads(listOfResources.get(i).getProperty(FileStore.TOTAL_NUM_DOWNLOADS).getInt());
					stats.setQuickestServiceTime(listOfResources.get(i).getProperty(FileStore.QUICKEST_SERVICE_TIME).getLong());
					stats.setSlowestServiceTime(listOfResources.get(i).getProperty(FileStore.SLOWEST_SERVICE_TIME).getLong());
					this.fileSatus.put(filename, stats);
				}else{
					FileStoreStatus stats = new FileStoreStatus();
					stats.setAverageServiceTime(listOfResources.get(i).getProperty(FileStore.AVG_SERVICE_TIME).getDouble());
					stats.setNumberOfDownloads(listOfResources.get(i).getProperty(FileStore.TOTAL_NUM_DOWNLOADS).getInt());
					stats.setQuickestServiceTime(listOfResources.get(i).getProperty(FileStore.QUICKEST_SERVICE_TIME).getLong());
					stats.setSlowestServiceTime(listOfResources.get(i).getProperty(FileStore.SLOWEST_SERVICE_TIME).getLong());
					this.fileSatus.put(filename, stats);
				}
			}
		}else{
			System.out.println("No Files");
		}
		this.collectFileStoreStats();
		
	}
	public List<String> getListOfFilenames(){
		ArrayList<String> listOfFileNames = new ArrayList<String>();
		Set<String> setOfFilename = this.fileSatus.keySet();
		Iterator<String> iter = setOfFilename.iterator();
		while (iter.hasNext()) {
			String key = iter.next();
			listOfFileNames.add(key);
		}
		return listOfFileNames;
	}
	public void collectFileStoreStats(){
		List<String> listOfFileNames = this.getListOfFilenames();
		int totalDownloads = 0 ;
		long quickestTime = 0 ;
		long slowestTime = 0;
		long averageTime = 0;
		for(int i = 0; i < listOfFileNames.size(); i++){
			FileStoreStatus status = this.getFileStatus(listOfFileNames.get(i));
			totalDownloads += status.getNumberOfDownloads() ;
			quickestTime += status.getQuickestServiceTime();
			slowestTime += status.getSlowestServiceTime();
			averageTime += status.getAverageServiceTime();
		}
		this.fileStoreStatus.setNumberOfDownloads(totalDownloads);
		this.fileStoreStatus.setQuickestServiceTime(quickestTime);
		this.fileStoreStatus.setSlowestServiceTime(slowestTime);
		this.fileStoreStatus.setAverageServiceTime(averageTime);
		
	}
	public FileStoreStatus getOverallStatus(){
		return this.fileStoreStatus;
	}
}
